//
// ==[ XPGL: eXPerimental Graphics Library ]== 
//
// Copyright 2006 JeGX / oZone3D.Net
// http://www.oZone3D.Net - jegx@ozone3d.net
//
// This SOFTWARE is distributed in the hope that it will be useful.
// TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
// *AS IS* AND oZone3D.Net DISCLAIM ALL WARRANTIES, EITHER EXPRESS
// OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL oZone3D.Net 
// BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
// WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
// BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
// ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF oZone3D.Net HAS
// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 
//
#include "stdafx.h"
#include "GlobalFunc.h"


void MSG_BOX_INFO( const char *strString, ... )
{
	char buf[4096]={0};
	va_list	argumentPtr;
	va_start( argumentPtr, strString );
	vsprintf( buf, strString, argumentPtr );	
	va_end( argumentPtr );

	MessageBox( NULL, buf, "Information", MB_OK|MB_ICONINFORMATION );

}

void MSG_BOX_WARNING( const char *strString, ... )
{
	char buf[4096]={0};
	va_list	argumentPtr;
	va_start( argumentPtr, strString );
	vsprintf( buf, strString, argumentPtr );	
	va_end( argumentPtr );

	MessageBox( NULL, buf, "WARNING", MB_OK|MB_ICONWARNING );
}


void MSG_BOX_ERROR( const char *strString, ... )
{
	char buf[4096]={0};
	va_list	argumentPtr;
	va_start( argumentPtr, strString );
	vsprintf( buf, strString, argumentPtr );	
	va_end( argumentPtr );

	MessageBox( NULL, buf, "ERROR", MB_OK|MB_ICONERROR );
}

void MSG_BOX_ERROR_T( const char *strString, ... )
{
	char buf[4096]={0};
	va_list	argumentPtr;
	va_start( argumentPtr, strString );
	vsprintf( buf, strString, argumentPtr );	
	va_end( argumentPtr );

	MessageBox( NULL, buf, "ERROR", MB_OK|MB_ICONERROR );
	exit(0);
}

size_t ExecuteProcess(std::wstring FullPathToExe, std::wstring Parameters,
					  size_t SecondsToWait)
{
	size_t iMyCounter = 0, iReturnVal = 0, iPos = 0;
	DWORD dwExitCode = 0;
	std::wstring sTempStr = L"";

	/* - NOTE - You should check here to see if the exe even exists */

	/* Add a space to the beginning of the Parameters */
	if (Parameters.size() != 0)
	{
		if (Parameters[0] != L' ')
		{
			Parameters.insert(0,L" ");
		}
	}

	/* The first parameter needs to be the exe itself */
	sTempStr = FullPathToExe;
	iPos = sTempStr.find_last_of(L"\\");
	sTempStr.erase(0, iPos +1);
	Parameters = sTempStr.append(Parameters);

	/*
	CreateProcessW can modify Parameters thus we
	allocate needed memory
	*/
	wchar_t * pwszParam = new wchar_t[Parameters.size() + 1];
	if (pwszParam == 0)
	{
		return 1;
	}
	const wchar_t* pchrTemp = Parameters.c_str();
	wcscpy_s(pwszParam, Parameters.size() + 1, pchrTemp);

	/* CreateProcess API initialization */
	STARTUPINFOW siStartupInfo;
	PROCESS_INFORMATION piProcessInfo;
	memset(&siStartupInfo, 0, sizeof(siStartupInfo));
	memset(&piProcessInfo, 0, sizeof(piProcessInfo));
	siStartupInfo.cb = sizeof(siStartupInfo);

	if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
		pwszParam, 0, 0, false,
		CREATE_DEFAULT_ERROR_MODE, 0, 0,
		&siStartupInfo, &piProcessInfo) != false)
	{
		/* Watch the process. */
		dwExitCode = WaitForSingleObject(piProcessInfo.hProcess,
			(SecondsToWait * 1000));
	}
	else
	{
		/* CreateProcess failed */
		iReturnVal = GetLastError();
	}

	/* Free memory */
	delete[]pwszParam;
	pwszParam = 0;

	/* Release handles */
	CloseHandle(piProcessInfo.hProcess);
	CloseHandle(piProcessInfo.hThread);

	return iReturnVal;
}

CString GetNameFromPath( const CString &src )
{
	return src.Right(src.GetLength()-src.ReverseFind('\\')-1);
}
CString GetFolderFromPath( const CString &src )
{
	return src.Left(src.ReverseFind('\\'));
}

CString GetSuffixFromPath( const CString &src)
{
	return (src.Right(src.GetLength()-src.ReverseFind('.')-1)).MakeLower();
}
CString G_RootFolder;
bool G_bSetCurrentFoldAsInit(false);

void LoadingDialog(std::ifstream &stream, CString suffix, CString title, CString initDir, CDialog *pDlg/*=NULL*/ )
{
	CString lower = suffix.MakeLower();
	CString upper = suffix.MakeUpper();
	CString szFilter = upper+" Files (*."+lower+")|*."+lower+"||";
	CFileDialog dlg_load(true,lower,"*."+lower,	OFN_HIDEREADONLY,szFilter.GetString(),pDlg);
	dlg_load.m_ofn.lpstrTitle = title;
	if(!G_bSetCurrentFoldAsInit)	dlg_load.m_ofn.lpstrInitialDir = initDir;
	if(dlg_load.DoModal()==IDOK) 
	{
		CString sFilename = dlg_load.GetPathName();
		if(G_bSetCurrentFoldAsInit)
			SetCurrentDirectory(GetFolderFromPath(sFilename));
		if (!sFilename.IsEmpty()){
			stream.close();stream.clear();
			stream.open(sFilename);
			if(!stream) {
				CString s;
				s.Format("Cannot open file: %s!",sFilename);
				AfxMessageBox(s);
			}
			else
				std::cout<<"#Loading from: "<<sFilename.Right( sFilename.GetLength()-sFilename.ReverseFind('\\')-1 )<<"\n"; 
		}
	}
	else
		stream.close();
}

bool LoadingDialog(CString &sFilename,CString suffix, CString title, CString initDir, CDialog *pDlg/*=NULL*/ )
{
	CString lower = suffix.MakeLower();
	CString upper = suffix.MakeUpper();
	CString szFilter = upper+" Files (*."+lower+")|*."+lower+"||";
	CFileDialog dlg_load(true,lower,"*."+lower,	OFN_HIDEREADONLY,szFilter.GetString(),pDlg);
	dlg_load.m_ofn.lpstrTitle = title;
	if(!G_bSetCurrentFoldAsInit)	dlg_load.m_ofn.lpstrInitialDir = initDir;
	if(dlg_load.DoModal()==IDOK) 
	{
		sFilename = dlg_load.GetPathName();
		if(G_bSetCurrentFoldAsInit)
			SetCurrentDirectory(GetFolderFromPath(sFilename));
		if (sFilename.IsEmpty()){
			CString s;		s.Format("the file path name is empty : %s!",sFilename );
			AfxMessageBox(s);
			return false;
		}
		else {
			std::cout<<"#Loading from: "<<sFilename.Right( sFilename.GetLength()-sFilename.ReverseFind('\\')-1 )<<"\n"; 
			return true;
		}
	}
	else 
		return false;
}

void SavingDialog(std::ofstream &stream, CString suffix, CString title, CString initDir, CDialog *pDlg/*=NULL*/ )
{
	CString lower = suffix.MakeLower();
	CString upper = suffix.MakeUpper();
	CString szFilter = upper+" Files (*."+lower+")|*."+lower+"||";
	CFileDialog dlg_save(false,lower,"*."+lower, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter.GetString(),pDlg);
	dlg_save.m_ofn.lpstrTitle = title;
	if(!G_bSetCurrentFoldAsInit)	dlg_save.m_ofn.lpstrInitialDir = initDir;
	if(dlg_save.DoModal()==IDOK) 
	{
		CString sFilename = dlg_save.GetPathName();
		if(G_bSetCurrentFoldAsInit)
			SetCurrentDirectory(GetFolderFromPath(sFilename));
		if (!sFilename.IsEmpty()){
			std::locale NarrowCharStyle("C");
			stream.imbue(NarrowCharStyle);
			stream.open(sFilename);
				if(!stream) {
				CString s;
				s.Format("Cannot open file: %s!",sFilename);
				AfxMessageBox(s);
			}
			else 
				std::cout<<"#Saving into: "<<sFilename.Right( sFilename.GetLength()-sFilename.ReverseFind('\\')-1 )<<"\n";
		}
	}
	else
		stream.close();
}


bool SavingDialog(CString &sFilename,CString suffix, CString title, CString initDir, CDialog *pDlg/*=NULL*/ )
{
	CString lower = suffix.MakeLower();
	CString upper = suffix.MakeUpper();
	CString szFilter = upper+" Files (*."+lower+")|*."+lower+"||";
	CFileDialog dlg_save(true,lower,"*."+lower,	OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter.GetString(),pDlg);
	dlg_save.m_ofn.lpstrTitle = title;
	if(!G_bSetCurrentFoldAsInit)	dlg_save.m_ofn.lpstrInitialDir = initDir;
	if(dlg_save.DoModal()==IDOK) 
	{
		sFilename = dlg_save.GetPathName();
		if(G_bSetCurrentFoldAsInit)
			SetCurrentDirectory(GetFolderFromPath(sFilename));
		if (sFilename.IsEmpty()){
			CString s;		s.Format("the file path name is empty : %s!",sFilename );
			AfxMessageBox(s);
			return false;
		}
		else {
			std::cout<<"#Saving into: "<<sFilename.Right( sFilename.GetLength()-sFilename.ReverseFind('\\')-1 )<<"\n";
			return true;
		}
	}
	else 
		return false;
}

void FindAllFile(CString strParent, CString ext, std::vector<CString> & pathList) 
{  
	pathList.clear();
	CFileFind finder;  
	BOOL   bFind = finder.FindFile(strParent +"\\"+ "*." + ext+" ");  
	while(bFind){	
		bFind = finder.FindNextFile();
		if(finder.IsDots())		continue; 

		CString name = finder.GetRoot()+finder.GetFileTitle()+"."+ext; //in case that the affix repeat!
		CString fullname = finder.GetFilePath();
		if(name!=fullname) continue;
		
		pathList.push_back(finder.GetFilePath());
	}
	//MSG_BOX_INFO("%d " + ext +" files has been found",pathList.size());
}   

char G_BrowserStartPath[MAX_PATH+1];
void SetBrowserStartPath(char* s){	strcpy(G_BrowserStartPath,s);	}

int	CALLBACK	BrowseCallbackProc(HWND hwnd, UINT msg, LPARAM lp, LPARAM pData)  
{	
	if(msg == BFFM_INITIALIZED){
		::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)G_BrowserStartPath);  
	}
	return 0;
}

#if MATLAB_AVAILABLE
bool initMatlab(std::vector<PFN_BOOL_VOID> &pf)	/* Start matlab Engine, then init the matlab func lib you need*/
{
	if( !mclInitializeApplication(NULL,0) ){   /* Initialize the MCR */
		std::cout << "Could not initialize the application!" << std::endl;
		return false;
	} 
	for(int i=0; i<static_cast<int>(pf.size()); ++i){		/* initialize lib*/
		if( !pf[i]() ){	
			std::cout << "Could not initialize No."<<i<<"th matlab func lib!\n";
			return false;
		}
	}
	return true;
}
void TerminateMatlab(){	mclTerminateApplication();} /*close matlab*/
#endif